package com.jiangyg.mall.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jiangyg.mall.admin.constant.AdminConstant;
import com.jiangyg.mall.admin.constant.ColumnConstant;
import com.jiangyg.mall.admin.dao.DepartDao;
import com.jiangyg.mall.admin.dao.DepartUserDao;
import com.jiangyg.mall.admin.dao.PermissionDao;
import com.jiangyg.mall.admin.dto.DepartDTO;
import com.jiangyg.mall.admin.dto.DepartUserDTO;
import com.jiangyg.mall.admin.entity.Depart;
import com.jiangyg.mall.admin.entity.DepartUser;
import com.jiangyg.mall.admin.entity.Permission;
import com.jiangyg.mall.admin.entity.User;
import com.jiangyg.mall.admin.vo.DepartVO;
import com.jiangyg.mall.admin.vo.UserVO;
import com.jiangyg.mall.core.enums.Enable;
import com.jiangyg.mall.core.exception.BusinessException;
import com.jiangyg.mall.core.support.restful.Pagination;
import com.jiangyg.mall.core.utils.I18n;
import com.jiangyg.mall.core.utils.bean.BeanUtils;
import com.jiangyg.mall.core.utils.tree.Tree;
import com.jiangyg.mall.core.utils.tree.TreeUtils;
import com.jiangyg.mall.db.mybatis.BaseServiceImpl;
import com.jiangyg.mall.db.mybatis.metadata.Pager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class DepartServiceImpl extends BaseServiceImpl<DepartDao, Depart> implements DepartService {

    private final PermissionDao permissionDao;

    private final DepartUserDao departUserDao;

    @Autowired
    public DepartServiceImpl(DepartDao departDao, DepartUserDao departUserDao, PermissionDao permissionDao) {
        super(departDao);
        this.departUserDao = departUserDao;
        this.permissionDao = permissionDao;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<Tree> departTree() throws Exception {
        List<DepartVO> departs = BeanUtils.transformList(this.baseMapper.selectList(null), DepartVO.class);
        final List<Tree> menus = departs.stream().map(DepartVO::toMenu).collect(Collectors.toList());
        return TreeUtils.instance(menus).getTree();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(DepartDTO dto) throws Exception {
        final QueryWrapper<Depart> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.CODE, dto.getCode());
        // 新增操作
        if (dto.getId() == null) {
            // 父级节点为空则，追加跟节点
            if (dto.getPid() == null) {
                dto.setPid(AdminConstant.ROOT_ID);
            }
            // 新增 code 不能重复
            final Integer count = this.baseMapper.selectCount(wrapper);
            if (count > 0) {
                throw BusinessException.instance("mall.admin.code.cannot.repeat", dto.getCode());
            }
            final Depart depart = new Depart();
            BeanUtils.copyProperties(depart, dto);
            return this.baseMapper.insert(depart) > 0;
        }
        // 要修改的数据
        final Depart depart = this.baseMapper.selectById(dto.getId());
        if (depart == null) {
            throw BusinessException.instance("mall.admin.common.update.notexist");
        }
        // 修改的 code 不能和其他部门数据重复
        if (StringUtils.equals(depart.getCode(), dto.getCode())) {
            final Integer count = this.baseMapper.selectCount(wrapper);
            if (count > 0) {
                throw BusinessException.instance("mall.admin.code.cannot.repeat", dto.getCode());
            }
        }
        // 修改操作
        BeanUtils.copyProperties(depart, dto);
        return this.baseMapper.updateById(depart) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveRelation(DepartUserDTO dto) {
        final List<Long> userIds = dto.getUserIds();
        if (CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        // 判断用户是否分配部门
        final QueryWrapper<DepartUser> wrapper = new QueryWrapper<>();
        wrapper.in(ColumnConstant.USER_ID, userIds);
        final Integer count = this.departUserDao.selectCount(wrapper);
        if (count > 0) {
            throw BusinessException.instance("mall.admin.depart.saveRelation.haveUser");
        }
        // 批量保存
        userIds.forEach(userId -> this.departUserDao.insert(new DepartUser(dto.getDepartId(), userId)));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRelation(DepartUserDTO dto) {
        final List<Long> userIds = dto.getUserIds();
        if (CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        final UpdateWrapper<DepartUser> wrapper = new UpdateWrapper<>();
        wrapper.eq(ColumnConstant.DEPART_ID, dto.getDepartId());
        wrapper.in(ColumnConstant.USER_ID, dto.getUserIds());
        return this.departUserDao.delete(wrapper) > 0;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public DepartVO selectById(Long departId, String details) throws Exception {
        final DepartVO depart = this.executeSelectById(departId, DepartVO.class);
        if (depart != null && StringUtils.isNotBlank(depart.getPid())) {
            Optional.ofNullable(this.baseMapper.selectById(Long.parseLong(depart.getPid()))).ifPresent(pd -> depart.setPname(pd.getName()));
        }
        return depart;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long departId) {
        // 优先判断是否有子部门
        final QueryWrapper<Depart> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.PID, departId);
        wrapper.eq(ColumnConstant.ENABLE, Enable.Y.scode);
        boolean haveDepart = this.baseMapper.selectCount(wrapper) > 0;
        if (haveDepart) {
            throw new BusinessException(I18n.getString("mall.admin.depart.delete.haveChildDepart"));
        }
        // 如果没有子部门的话，则查询部门下是否有用户
        boolean existUser = this.baseMapper.countUserByDepartId(departId) > 0;
        if (existUser) {
            throw new BusinessException(I18n.getString("mall.admin.depart.delete.haveUser"));
        }
        // 删除部门权限信息
        final UpdateWrapper<Permission> deleteWrapper = new UpdateWrapper<>();
        deleteWrapper.eq(ColumnConstant.REFERENCE_ID, departId);
        this.permissionDao.delete(deleteWrapper);
        // 删除操作
        return this.baseMapper.deleteById(departId) > 0;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Pagination<UserVO> selectUserList(Pagination<UserVO> pagination, Long departId) throws Exception {
        final Pager<User> pager = Pager.from(pagination);
        final List<User> users = departUserDao.selectUserByDepartId(pager, departId);
        pagination.setRecords(BeanUtils.transformList(users, UserVO.class));
        return pagination;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<UserVO> selectUnallocatedUserList() throws Exception {
        final List<User> users = departUserDao.selectUnallocatedUserList();
        return BeanUtils.transformList(users, UserVO.class);
    }

}
